﻿using System.Diagnostics;
using System.Threading.Tasks.Sources;

int num = 0;
_ = Task.Factory.StartNew(() =>
{
    Stopwatch sw = Stopwatch.StartNew();
    while (true)
    {
        Thread.Sleep(5000);
        double speed = num / sw.Elapsed.TotalSeconds;
        Console.WriteLine($"10000个循环干活总速度={speed:#### ####.0} 次/秒");
    }
}, TaskCreationOptions.LongRunning);

async ValueTask func(int i)
{
    using var taskSource = new DelayTaskSource(TimeSpan.FromMilliseconds(15));
    while (true)
    {
        await taskSource.CreateValueTask();
        // Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.ffff} - {i}");

        Interlocked.Increment(ref num); // 干活
    }
}

for (int i = 0; i < 10000; i++)
{
    _ = func(i);
}

Console.WriteLine("开始");
Console.ReadLine();

sealed class DelayTaskSource : IValueTaskSource, IDisposable
{
    private readonly Timer timer;
    private readonly TimeSpan delay;
    private ManualResetValueTaskSourceCore<object?> sourceCore = new();

    public DelayTaskSource(TimeSpan delay)
    {
        this.delay = delay;
        this.timer = new Timer(this.TimerCallback, null, Timeout.Infinite, Timeout.Infinite);
    }

    private void TimerCallback(object? state)
    {
        this.sourceCore.SetResult(null);
    }

    public ValueTask CreateValueTask()
    {
        this.sourceCore.Reset();
        this.timer.Change(this.delay, Timeout.InfiniteTimeSpan);
        return new ValueTask(this, this.sourceCore.Version);
    }

    public void GetResult(short token)
    {
        sourceCore.GetResult(token);
    }

    public ValueTaskSourceStatus GetStatus(short token)
    {
        return sourceCore.GetStatus(token);
    }

    public void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
    {
        sourceCore.OnCompleted(continuation, state, token, flags);
    }

    public void Dispose()
    {
        this.timer.Dispose();
    }
}